#include "..\..\Header\Device\fwWin32Context.h"

#if CURRENT_PLATFORM == PLATFORM_WIN32

#include <Windows.h>

Win32Context::Win32Context(int iWidth, int iHeight, char* wcsTitle, int iFlags)
	: PlatformContext(),
	m_szTitle(wcsTitle),
	m_iWidth(iWidth), m_iHeight(iHeight),
	m_iFlags(iFlags)
{
}

int Win32Context::Init()
{
	LOGI("Win32\n");
	w32CreateWindows();
	return m_pGameContext->Init();
}

void Win32Context::Destroy()
{
	LOGI("Win32\n");
	m_pGameContext->Destroy();
	SAFE_DEL(m_pGameContext);
}

void Win32Context::Run()
{
	LOGI("============================================================\n");
	LOGI("Game loop start=============================================\n");
	LOGI("============================================================\n");
	MSG msg = { 0 };
	int done = 0;
	DWORD lastTime = GetTickCount();

	while (!done)
	{
		int gotMsg = (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0);
		DWORD curTime = GetTickCount();
		float deltaTime = (float)(curTime - lastTime) / 1000.0f;
		lastTime = curTime;

		if (gotMsg)
		{
			if (msg.message == WM_QUIT)
			{
				done = 1;
			}
			else
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		else
		{
			SendMessage(m_eglHWND, WM_PAINT, 0, 0);
		}

		if (m_pGameContext)
			m_pGameContext->Update(deltaTime);
		eglSwapBuffers(m_eglDisplay, m_eglSurface);
	}
	LOGI("============================================================\n");
	LOGI("Game loop end===============================================\n");
	LOGI("============================================================\n");
}

EGLBoolean Win32Context::w32CreateESContext(EGLint attrs[])
{
	EGLint numConfigs;
	EGLint majorVersion;
	EGLint minorVersion;
	EGLDisplay display;
	EGLContext context;
	EGLSurface surface;
	EGLConfig config;
	EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };

	display = eglGetDisplay(GetDC(m_eglHWND));
	if (display == EGL_NO_DISPLAY)
	{
		return EGL_FALSE;
	}

	if (!eglInitialize(display, &majorVersion, &minorVersion))
	{
		return EGL_FALSE;
	}

	if (!eglGetConfigs(display, NULL, 0, &numConfigs))
	{
		return EGL_FALSE;
	}

	if (!eglChooseConfig(display, attrs, &config, 1, &numConfigs))
	{
		return EGL_FALSE;
	}

	surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)m_eglHWND, NULL);
	if (surface == EGL_NO_SURFACE)
	{
		return EGL_FALSE;
	}

	context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
	if (context == EGL_NO_CONTEXT)
	{
		return EGL_FALSE;
	}

	if (!eglMakeCurrent(display, surface, surface, context))
	{
		return EGL_FALSE;
	}

	m_eglDisplay = display;
	m_eglSurface = surface;
	m_eglContext = context;

	return EGL_TRUE;
}

EGLBoolean Win32Context::w32CreateClientWindows()
{
	WNDCLASS wndclass = { 0 };
	DWORD    wStyle = 0;
	RECT     windowRect;
	HINSTANCE hInstance = GetModuleHandle(NULL);


	wndclass.style = CS_OWNDC;
	wndclass.lpfnWndProc = (WNDPROC)w32WindowsProc;
	wndclass.hInstance = hInstance;
	wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wndclass.lpszClassName = TEXT("opengles2.0");

	if (!RegisterClass(&wndclass))
		return FALSE;

	wStyle = WS_VISIBLE | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION;

	// Adjust the window rectangle so that the client area has
	// the correct number of pixels
	windowRect.left = 0;
	windowRect.top = 0;
	windowRect.right = m_iWidth;
	windowRect.bottom = m_iHeight;

	AdjustWindowRect(&windowRect, wStyle, FALSE);

	m_eglHWND = CreateWindow(
		"opengles2.0",
		m_szTitle,
		wStyle,
		0,
		0,
		windowRect.right - windowRect.left,
		windowRect.bottom - windowRect.top,
		NULL,
		NULL,
		hInstance,
		NULL);

	if (m_eglHWND == NULL)
		return GL_FALSE;

	ShowWindow(m_eglHWND, TRUE);

	return GL_TRUE;
}

EGLBoolean Win32Context::w32CreateWindows()
{
	EGLint attribList[] =
	{
		EGL_RED_SIZE, 5,
		EGL_GREEN_SIZE, 6,
		EGL_BLUE_SIZE, 5,
		EGL_ALPHA_SIZE, (m_iFlags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE,
		EGL_DEPTH_SIZE, (m_iFlags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE,
		EGL_STENCIL_SIZE, (m_iFlags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE,
		EGL_SAMPLE_BUFFERS, (m_iFlags & ES_WINDOW_MULTISAMPLE) ? 1 : 0,
		EGL_NONE
	};

	if (!w32CreateClientWindows())
	{
		return GL_FALSE;
	}

	if (!w32CreateESContext(attribList))
	{
		return GL_FALSE;
	}

	return EGL_TRUE;
}

LRESULT Win32Context::w32WindowsProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	LRESULT  lRet = 1;

	switch (uMsg)
	{
	case WM_CREATE:
		break;
	case WM_PAINT:
	{
		if (m_pGameContext)
			m_pGameContext->Draw();
		ValidateRect(hWnd, NULL);
	}
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_KEYDOWN:
		if (m_pGameContext)
			//m_pGameContext->m_KeyFunc((unsigned char)wParam, true);
		break;
	case WM_KEYUP:
		if (m_pGameContext)
			//m_pInstance->m_KeyFunc((unsigned char)wParam, false);
		break;
	default:
		lRet = DefWindowProc(hWnd, uMsg, wParam, lParam);
		break;
	}

	return lRet;
}

#endif